// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import {IACLManager} from "./interfaces/IACLManager.sol";
import {InvestmentManager} from "./InvestmentManager.sol";
import {SwapManager} from "./SwapManager.sol";
import {LendingManager} from "./LendingManager.sol";
import {IPool} from "./interfaces/IPool.sol";

contract DeltaNeutralPortfolio is InvestmentManager, SwapManager, LendingManager {
    using SafeERC20 for IERC20;

    address public ACLManager;
    mapping(address => bool) public allowedAssets;
    mapping(address => bool) public allowedDexs;
    mapping(address => bool) public allowedLendings;

    constructor(
        address newAclManager,
        address[] memory newAllowedAssets,
        address[] memory newAllowedDexs,
        address[] memory newAllowedLendings
    ) InvestmentManager() SwapManager() LendingManager() {
        ACLManager = newAclManager;

        for (uint256 i; i < newAllowedAssets.length; i++) {
            allowedAssets[newAllowedAssets[i]] = true;
        }

        for (uint256 i; i < newAllowedDexs.length; i++) {
            allowedDexs[newAllowedDexs[i]] = true;
        }

        for (uint256 i; i < newAllowedLendings.length; i++) {
            allowedLendings[newAllowedLendings[i]] = true;
        }
    }

    function entry() external virtual override nonReentrant onlyActivePool {
        IERC20(IPool(activePool).baseToken()).safeTransferFrom(
            activePool,
            address(this),
            IPool(activePool).depositsAmount()
        );
    }

    function exit() external virtual override nonReentrant onlyActivePool {
        uint256 balance = IERC20(IPool(activePool).baseToken()).balanceOf(address(this));
        IERC20(IPool(activePool).baseToken()).safeTransfer(activePool, balance);
    }

    function emergency() external virtual override nonReentrant onlyProtocolAdmin {}

    function isAssetAllowed(address asset) public view virtual override(SwapManager, LendingManager) returns (bool) {
        return allowedAssets[asset];
    }

    function isDexAllowed(address dex) public view virtual override(SwapManager) returns (bool) {
        return allowedDexs[dex];
    }

    function isLendingAllowed(address lending) public view virtual override(LendingManager) returns (bool) {
        return allowedLendings[lending];
    }

    modifier onlyProtocolAdmin() override(InvestmentManager) {
        require(
            IACLManager(ACLManager).isProtocolAdmin(msg.sender),
            "DeltaNeutralPortfolio: caller is not protocol admin"
        );
        _;
    }

    modifier onlyProtocolTrader() override(InvestmentManager, SwapManager, LendingManager) {
        require(
            IACLManager(ACLManager).isProtocolTrader(msg.sender),
            "DeltaNeutralPortfolio: caller is not protocol trader"
        );
        _;
    }
}
